from typing import Optional, Dict, Any, Tuple
from fastapi import UploadFile, HTTPException
from sqlalchemy.orm import Session
from loguru import logger

from app.models.video import Video
from app.utils.database import db_manager
from app.utils.file_utils import FileUtils
from config import config

class VideoUploadService:
    """视频上传服务"""
    
    def __init__(self):
        self.file_utils = FileUtils()
    
    async def upload_video(
        self, 
        file: UploadFile, 
        original_language: Optional[str] = None,
        target_language: Optional[str] = None,
        description: Optional[str] = None
    ) -> Dict[str, Any]:
        """
        上传视频文件
        
        Args:
            file: 上传的文件
            original_language: 原始语言代码
            target_language: 目标语言代码
            description: 视频描述
            
        Returns:
            视频信息字典
        """
        try:
            # 验证文件
            if not file.filename:
                raise HTTPException(status_code=400, detail="文件名不能为空")
            
            # 检查文件扩展名
            file_ext = file.filename.lower().split('.')[-1]
            if f'.{file_ext}' not in config.SUPPORTED_VIDEO_FORMATS:
                raise HTTPException(
                    status_code=400, 
                    detail=f"不支持的文件格式: {file_ext}"
                )
            
            # 保存文件
            file_path, stored_filename = self.file_utils.save_uploaded_file(
                file, file.filename
            )
            
            # 验证视频文件
            is_valid, error_msg = self.file_utils.validate_video_file(file_path)
            if not is_valid:
                # 删除无效文件
                self.file_utils.delete_file(file_path)
                raise HTTPException(status_code=400, detail=error_msg)
            
            # 获取视频信息
            video_info = self.file_utils.get_video_info(file_path)
            
            # 保存到数据库
            video_data = {
                'original_filename': file.filename,
                'stored_filename': stored_filename,
                'file_path': file_path,
                'file_size': video_info.get('file_size', 0),
                'duration': video_info.get('duration'),
                'resolution': video_info.get('resolution'),
                'frame_rate': video_info.get('frame_rate'),
                'original_language': original_language,
                'target_language': target_language,
                'description': description,
                'status': 'uploaded'
            }
            
            video_id = self._save_video_to_db(video_data)
            
            logger.info(f"视频上传成功: {video_id}")
            
            # 在会话中获取视频信息
            with db_manager.get_session() as session:
                video_info = session.query(Video).filter(Video.id == video_id).first()
                if video_info:
                    video_dict = video_info.to_dict()
                else:
                    # 如果查询失败，创建基本信息
                    video_dict = {
                        'id': video_id,
                        'original_filename': video_data['original_filename'],
                        'file_size': video_data['file_size'],
                        'status': video_data['status']
                    }
            
            return {
                'success': True,
                'video_id': video_id,
                'message': '视频上传成功',
                'video_info': video_dict
            }
            
        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"视频上传失败: {e}")
            raise HTTPException(status_code=500, detail=f"视频上传失败: {str(e)}")
    
    def extract_audio_from_video(self, video_id: str) -> Dict[str, Any]:
        """
        从视频中提取音频
        
        Args:
            video_id: 视频ID
            
        Returns:
            提取结果
        """
        try:
            # 在会话中获取视频信息
            with db_manager.get_session() as session:
                video = session.query(Video).filter(Video.id == video_id).first()
                if not video:
                    raise HTTPException(status_code=404, detail="视频不存在")
                
                if video.audio_extracted:
                    return {
                        'success': True,
                        'message': '音频已提取',
                        'audio_path': video.audio_path
                    }
                
                # 提取音频
                audio_path = self.file_utils.extract_audio(video.file_path)
            
            # 更新数据库
            with db_manager.get_session() as session:
                db_video = session.query(Video).filter(Video.id == video_id).first()
                if db_video:
                    db_video.audio_path = audio_path
                    db_video.audio_extracted = True
                    db_video.status = 'audio_extracted'
                    session.add(db_video)
                    session.commit()
            
            logger.info(f"音频提取成功: {audio_path}")
            
            return {
                'success': True,
                'message': '音频提取成功',
                'audio_path': audio_path
            }
            
        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"音频提取失败: {e}")
            raise HTTPException(status_code=500, detail=f"音频提取失败: {str(e)}")
    
    def get_video_info(self, video_id: str) -> Dict[str, Any]:
        """
        获取视频信息
        
        Args:
            video_id: 视频ID
            
        Returns:
            视频信息
        """
        try:
            video = self._get_video_by_id(video_id)
            if not video:
                raise HTTPException(status_code=404, detail="视频不存在")
            
            # 在会话中获取视频信息
            with db_manager.get_session() as session:
                video_info = session.query(Video).filter(Video.id == video_id).first()
                if video_info:
                    video_dict = video_info.to_dict()
                else:
                    raise HTTPException(status_code=404, detail="视频不存在")
            
            return {
                'success': True,
                'video_info': video_dict
            }
            
        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"获取视频信息失败: {e}")
            raise HTTPException(status_code=500, detail=f"获取视频信息失败: {str(e)}")
    
    def list_videos(self, limit: int = 10, offset: int = 0) -> Dict[str, Any]:
        """
        获取视频列表
        
        Args:
            limit: 限制数量
            offset: 偏移量
            
        Returns:
            视频列表
        """
        try:
            with db_manager.get_session() as session:
                videos = session.query(Video).order_by(
                    Video.created_at.desc()
                ).offset(offset).limit(limit).all()
                
                total = session.query(Video).count()
                
                # 在会话中转换视频对象为字典
                video_dicts = []
                for video in videos:
                    video_dicts.append(video.to_dict())
                
                return {
                    'success': True,
                    'videos': video_dicts,
                    'total': total,
                    'limit': limit,
                    'offset': offset
                }
                
        except Exception as e:
            logger.error(f"获取视频列表失败: {e}")
            raise HTTPException(status_code=500, detail=f"获取视频列表失败: {str(e)}")
    
    def delete_video(self, video_id: str) -> Dict[str, Any]:
        """
        删除视频
        
        Args:
            video_id: 视频ID
            
        Returns:
            删除结果
        """
        try:
            video = self._get_video_by_id(video_id)
            if not video:
                raise HTTPException(status_code=404, detail="视频不存在")
            
            # 删除文件
            self.file_utils.delete_file(video.file_path)
            if video.audio_path:
                self.file_utils.delete_file(video.audio_path)
            
            # 从数据库删除
            with db_manager.get_session() as session:
                session.delete(video)
            
            logger.info(f"视频删除成功: {video_id}")
            
            return {
                'success': True,
                'message': '视频删除成功'
            }
            
        except HTTPException:
            raise
        except Exception as e:
            logger.error(f"删除视频失败: {e}")
            raise HTTPException(status_code=500, detail=f"删除视频失败: {str(e)}")
    
    def _save_video_to_db(self, video_data: Dict[str, Any]) -> str:
        """保存视频信息到数据库，返回视频ID"""
        with db_manager.get_session() as session:
            video = Video(**video_data)
            session.add(video)
            session.commit()
            return video.id
    
    def _get_video_by_id(self, video_id: str) -> Optional[Video]:
        """根据ID获取视频"""
        with db_manager.get_session() as session:
            return session.query(Video).filter(Video.id == video_id).first() 